package domain

import (
	"github.com/hlhutu/gormplus"
	"ruoyi-go/internal/framework/db"
)

type SysMenu struct {
	// 菜单ID
	MenuId int `json:"menuId" gorm:"column:menu_id" form:"menuId"`
	// 菜单名称
	MenuName string `json:"menuName" gorm:"column:menu_name" form:"menuName"`
	// 父菜单名称
	ParentName string `json:"parentName" gorm:"column:parent_name" form:"parentName"`
	// 父菜单ID
	ParentId int `json:"parentId" gorm:"column:parent_id" form:"parentId"`
	// 显示顺序
	OrderNum int `json:"orderNum" gorm:"column:order_num" form:"orderNum"`
	// 路由地址
	Path string `json:"path" gorm:"column:path" form:"path"`
	// 组件路径
	Component string `json:"component" gorm:"column:component" form:"component"`
	// 路由参数
	Query string `json:"query" gorm:"column:query" form:"query"`
	// 路由名称，默认和路由地址相同的驼峰格式
	RouteName string `json:"routeName" gorm:"column:route_name" form:"routeName"`
	// 是否为外链（0是 1否）
	IsFrame string `json:"isFrame" gorm:"column:is_frame" form:"isFrame"`
	// 是否缓存（0缓存 1不缓存）
	IsCache string `json:"isCache" gorm:"column:is_cache" form:"isCache"`
	// 类型（M目录 C菜单 F按钮）
	MenuType string `json:"menuType" gorm:"column:menu_type" form:"menuType"`
	// 显示状态（0显示 1隐藏）
	Visible string `json:"visible" gorm:"column:visible" form:"visible"`
	// 菜单状态（0正常 1停用）
	Status string `json:"status" gorm:"column:status" form:"status"`
	// 权限字符串
	Perms string `json:"perms" gorm:"column:perms" form:"perms"`
	// 菜单图标
	Icon string `json:"icon" gorm:"column:icon" form:"icon"`

	/**
	冗余字段
	*/

	// 子菜单
	Children []*SysMenu `json:"children" gorm:"-" form:"children"`
}

func (m SysMenu) TableName() string {
	return "sys_menu"
}

type sysMenuModel struct {
	gormplus.Model[SysMenu]
}

var sysMenuModelInst *sysMenuModel

func SysMenuModel() *sysMenuModel {
	if sysMenuModelInst == nil {
		sysMenuModelInst = &sysMenuModel{Model: gormplus.NewModel(SysMenu{}, db.GormDB)}
	}
	return sysMenuModelInst
}

// SelectMenuPermsByRoleId 根据roleId查询所有权限
func (s *sysMenuModel) SelectMenuPermsByRoleId(roleId int) []string {
	var results []*SysMenu
	err := db.GormDB.Table("sys_menu m").
		Select("distinct m.perms").
		Joins("left join sys_role_menu rm on m.menu_id = rm.menu_id").
		Where("m.status = '0' and rm.role_id = ?", roleId).
		Scan(&results).Error
	if err != nil {
		panic(err)
	}
	var permissions []string
	for _, result := range results {
		permissions = append(permissions, result.Perms)
	}
	return permissions
}

// SelectMenuPermsByUserId 根据userId查询所有权限
func (s *sysMenuModel) SelectMenuPermsByUserId(userId int) []string {
	var results []*SysMenu
	err := db.GormDB.Table("sys_menu m").
		Select("distinct m.perms").
		Joins("left join sys_role_menu rm on m.menu_id = rm.menu_id").
		Joins("left join sys_user_role ur on rm.role_id = ur.role_id").
		Joins("left join sys_role r on r.role_id = ur.role_id").
		Where("m.status = '0' and r.status = '0' and ur.user_id = ?", userId).
		Scan(&results).Error
	if err != nil {
		panic(err)
	}
	var permissions []string
	for _, result := range results {
		permissions = append(permissions, result.Perms)
	}
	return permissions
}

// SelectMenuTreeAll 查询完整菜单树
func (s *sysMenuModel) SelectMenuTreeAll() []*SysMenu {
	var menus []*SysMenu
	tx := db.GormDB.Table("sys_menu m").
		Select("distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.route_name, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time").
		Where("m.menu_type in (?) and m.status = ?", []string{"M", "C"}, 0).
		Order("m.parent_id, m.order_num").
		Find(&menus)
	if tx.Error != nil {
		panic(tx.Error)
	}
	return menus
}

// SelectMenuTreeByUserId retrieves the menu tree authorized for a specific user based on their user ID.
func (s *sysMenuModel) SelectMenuTreeByUserId(userId int) []*SysMenu {
	var menus []*SysMenu
	tx := db.GormDB.Table("sys_menu m").
		Select("distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.route_name, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time").
		Joins("left join sys_role_menu rm on m.menu_id = rm.menu_id").
		Joins("left join sys_user_role ur on rm.role_id = ur.role_id").
		Joins("left join sys_role ro on ur.role_id = ro.role_id").
		Joins("left join sys_user u on ur.user_id = u.user_id").
		Where("u.user_id = ? and m.menu_type in (?, ?) and m.status = ? and ro.status = ?", userId, "M", "C", 0, 0).
		Order("m.parent_id, m.order_num").Find(&menus)
	if tx.Error != nil {
		panic(tx.Error)
	}
	return menus
}
